﻿#pragma once
#include "yzrutil.h"
#include <cmath>

namespace yzrilyzr_type{
	class Complex{
	public:
	double re;   // the real part
	double im;   // the imaginary part
	Complex() :re(0), im(0){}
	Complex(double real, double imag) : re(real), im(imag){}
	yzrilyzr_lang::String toString() const{
		if(im == 0) return std::to_string(re);
		if(re == 0) return std::to_string(im) + "i";
		if(im < 0) return std::to_string(re) + " - " + std::to_string(-im) + "i";
		return std::to_string(re) + " + " + std::to_string(im) + "i";
	}
	Complex operator+(Complex b)const{
		double real=re + b.re;
		double imag=im + b.im;
		return Complex(real, imag);
	}
	double abs()const{
		return std::hypot(re, im);
	}
	double phase()const{
		return std::atan2(im, re);
	}
	Complex operator-(Complex b)const{
		double real=re - b.re;
		double imag=im - b.im;
		return Complex(real, imag);
	}
	Complex operator*(double alpha)const{
		return Complex(alpha * re, alpha * im);
	}
	Complex conjugate()const{
		return Complex(re, -im);
	}
	double value()const{
		return std::sqrt(re * re + im * im);
	}
	Complex exp(){
		return Complex(std::exp(re) * std::cos(im), std::exp(re) * std::sin(im));
	}
	Complex tan()const{
		return sin().divides(cos());
	}
	Complex divides(Complex b)const{
		return multiple(b.reciprocal());
	}
	Complex sin()const{
		return Complex(std::sin(re) * std::cosh(im), std::cos(re) * std::sinh(im));
	}
	Complex cos()const{
		return Complex(std::cos(re) * std::cosh(im), -std::sin(re) * std::sinh(im));
	}
	Complex multiple(Complex b)const{
		double real=re * b.re - im * b.im;
		double imag=re * b.im + im * b.re;
		return Complex(real, imag);
	}
	Complex reciprocal()const{
		double scale=re * re + im * im;
		return Complex(re / scale, -im / scale);
	}
	};
}